home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Sound Cards
/
Programming Sound Cards.iso
/
sound_70
/
ref.doc
< prev
next >
Wrap
Text File
|
1995-01-01
|
14KB
|
353 lines
Rebooting:
40:72h holds 1234h for warm boot, and 4321h (or != 1234h) for cold boot
jmp to F000:FFF0h
-----------------------------------------------------------------------------
Speaker:
Port 61h read (ISA, EISA)
Bit [7] = Parity check (parity error)
Bit [6] = Channel check (ISA parity error)
Bit [5] = Timer 2 output
Bit [4] = Toggles with each refresh request
Bit [3] = Channel check enable (enable ISA parity check)
Bit [2] = Parity check enable (enable parity check)
Bit [1] = Speaker data enable (Timer 2 output enable)
Bit [0] = Speaker timer enable (Timer 2 gate enable)
Port 61h write (ISA, EISA)
Bit [7-4] = Reserved
Bit [3] = Channel check enable (enable ISA parity check)
Bit [2] = Parity check enable (enable parity check)
Bit [1] = Speaker data enable (Timer 2 output enable)
Bit [0] = Speaker timer enable (Timer 2 gate enable)
Port 61h write (XT only)
Bit [7] = 1 Clear keyboard
Bit [6] = 0 Hold keyboard clock low
Bit [5] = 0 I/O check enable
Bit [4] = 0 RAM parity check enable
Bit [3] = 0 Read low switches
Bit [2] = Reserved
Bit [1] = 1 Speaker data enable (Timer 2 output enable)
Bit [0] = 1 Speaker timer enable (Timer 2 gate enable)
-----------------------------------------------------------------------------
8254 Programmable Interval Timer (PIT)
Counter 0: System timer, Always on, 1.193MHz, IRQ0
Counter 1: Refresh request, Always on, 1.193MHz, Request refresh
Counter 2: Speaker frequency, enable speaker, 1.193MHz, Speaker signal
Port 40h Read/Write Counter 0
Port 41h Read/Write Counter 1
Port 42h Read/Write Counter 2
Port 43h Write/Only Control register
Bits [7..6] Select counter
00 Counter 0
01 Counter 1
10 Counter 2
11 Read back command
Bits [5..4] Operation
00 Latch counter (bits[3..1] are don't care)
01 Read/Write LSB only
10 Read/Write MSB only
11 Read/Write LSB, then MSB
Bits [3..1] Operating mode selection
000 Mode 0: interrupt on terminal count
001 Mode 1: hardware triggered one-shot
x10 Mode 2: rate generator
x11 Mode 3: square-wave generator
100 Mode 4: software triggered strobe
101 Mode 5: hardware triggered strobe
xxx For latch counter operation
Bit [0] Binary or BCD count down format
0 Binary (16-bit) count down
1 BCD count down (four-decades)
x For latch counter operation
Port 43h Write/Only Control Register (read-back command)
Bits [7..6]
11 Read back command
Bits [5..4]
0x latches the state of the CE in COL and COH
x0 latches status of selected counters into the
status register.
Bits [3..0]
1xx0 Selects counter 2
x1x0 Selects counter 1
xx10 Selects counter 0
If status is latched, status is read first through counter read/write
register.
If count is latched, the count is read back through counter read/write
retister, one or two reads depending on how programmed.
Status Byte Latched
Bit [7]
0 OUT signal 0 (low)
1 OUT signal 1 (high)
Bit [6]
0 Counter loaded from the counter input registers,
count can be read.
1 Write to the congtrol register or the counter, but
the new value has not been loaded into CE.
Bits [5..4]
00 Reserved
01 Read/Write LSByte
10 Read/Write MSByte
11 Read/Write LSByte then MSByte
Bits [3..1]
000 Mode 0
001 Mode 1
010 Mode 2
011 Mode 3
100 Mode 4
101 Mode 5
Bit [0]
0 Binary (16-bit) count down
1 BCD count down (four decades)
1.19318MHz = 4.77273MHz/4. Typically Counter 0 is set for 0000h (max
count) 54.925ms. There are 1573040 tics per day.
This is an example code segment that shows how to speed up the timer
resolution. I had no problem with this piece of code on a 486DX2-66,
on slower machines you may need to slow it down.
---- cut ----
.model tiny
.code
org 100h
entry:
jmp over
old08vec dd ?
keeptime dw 0000h
isr08h:
inc word ptr cs:[keeptime]
; at this point, you have a sped up interrupt
; be careful not overload the processor
cmp cs:[_counter],0FFFFh
jz notenabled
notenabled:
cmp word ptr cs:[keeptime],1000h
jz handoff
push ax
mov al,20h
out 20h,al
pop ax
iret
handoff:
mov word ptr cs:[keeptime],0000h
jmp dword ptr cs:[old08vec]
over:
mov ax,3508h
int 21h
mov word ptr cs:[old08vec],bx
mov word ptr cs:[old08vec+2],es
mov ax,2508h
mov dx,offset isr08h
;tiny no ds
int 21h
mov al,10h
out 40h,al
mov al,00h
out 40h,al
mov ah,00h
int 16h
xor al,al
out 40h,al
out 40h,al
mov ax,2508h
mov dx,word ptr cs:[old08vec]
mov ds,word ptr cs:[old08vec+2]
int 21h
mov ax,4C00h
int 21h
end entry
---- cut ----
The speaker timer (counter 2) can also be used for high resolution
timing for periods less than 55ms total, using this timer avoids
the potential harm to the system like Counter 0 or 1. One
implementation might be:
Enable timer 2 gate, disable timer 2 output:
out(61h,01h)
Set Counter 2 for interrupt on terminal count:
out(43h,B0h)
Set MSB to start count and halt counting:
out(42h,FFh)
Set LSB to start count and start counting:
out(42h,FFh)
Perform task to be timed (with no speaker access)
Latch count:
out(43h,C0h)
Read count:
LSByte=in(42h)
MSByte=in(42h)
-----------------------------------------------------------------------------
8259 Programmable Interrupt Controllers (PICs)
Port 20h write a 20h to clear interrupts (during isr)
can write a 60h+irq, but that is not necessary if
the PIC is configured for modes that preserve the fully
nested structure (which is how you will find it normally)
Port 21h read/write, enables and disables irqs 0-7,
0 = enabled, 1 = disabled
Bit [7] irq 7
Bit [6] irq 6
Bit [5] irq 5
Bit [4] irq 4
Bit [3] irq 3
Bit [2] irq 2
Bit [1] irq 1
Bit [0] irq 0
Port A0h write a 20h to clear interrupts (during isr)
can write 60h+irq-8, see above (Port 20h)
Port A1h read/write, enables and disables irqs 8-15,
0 = enable, 1 = disable
Bit [7] irq 15
Bit [6] irq 14
Bit [5] irq 13
Bit [4] irq 12
Bit [3] irq 11
Bit [2] irq 10
Bit [1] irq 9
Bit [0] irq 8
--------------------------------------------------------------------------------
8237 DMA Controller (DMAC)
Port 0000h DMA Channel 0, Memory address register (r/w)
16-bit, LSByte first then MSByte
Port 0001h DMA Channel 0, Transfer count register (r/w)
16-bit, LSByte first then MSByte
Port 0002h DMA Channel 1, Memory address register (r/w)
Port 0003h DMA Channel 1, Transfer count register (r/w)
Port 0004h DMA Channel 2, Memory address register (r/w)
Port 0005h DMA Channel 2, Transfer count register (r/w)
Port 0006h DMA Channel 3, Memory address register (r/w)
Port 0007h DMA Channel 3, Transfer count register (r/w)
Port 0008h DMA Status register (r)
bit [7] = 1 Channel 3 request
bit [6] = 1 Channel 2 request
bit [5] = 1 Channel 1 request
bit [4] = 1 Channel 0 request
bit [3] = 1 Terminal count on channel 3
bit [2] = 1 Terminal count on channel 2
bit [1] = 1 Terminal count on channel 1
bit [0] = 1 Terminal count on channel 0
Port 000Ah DMA Channel 0-3 Mask register (r/w)
bits [7..3] = 0 reserved
bit [2] = 0 Clear mask bit
1 Set mask bit
bits [1..0] = 00 Select channel 0
01 Select channel 1
10 Select channel 2
11 Select channel 3
Port 000Bh DMA Channel 0-3 Mode register (r/w)
bits [7..6] = 00 Demand mode
01 Single mode
10 Block mode
11 Cascade mode
bit [5] = 0 Address increment select
bit [4] = 0 Autoinitialized
1 Non-autoinitialized
bits [3..2] = 00 Verify operation
01 Write operation
10 Read operation
11 Reserved
bits [1..0] = 00 Select channel 0
01 Select channel 1
10 Select channel 2
11 Select channel 3
Port 000Ch DMA Clear Byte Pointer (w)
Port 000Dh DMA Master Clear (w)
Port 000Eh DMA Clear Mask register (w)
Port 000Fh DMA DMA Channel 0-3 Write Mask register (w)
bits [7..4] = 0 reserved
bit [3] = 0 Unmask channel 3 mask bit
1 Set channel 3 mask bit
0 Unmask channel 2 mask bit
1 Set channel 2 mask bit
0 Unmask channel 1 mask bit
1 Set channel 1 mask bit
0 Unmask channel 0 mask bit
1 Set channel 0 mask bit
Port 0019h DMA Scratch register (r/w)
Port 0081h DMA channel 2, page table address register (r/w)
Port 0082h DMA channel 3, page table address register (r/w)
Port 0083h DMA channel 1, page table address register (r/w)
Port 0087h DMA channel 0, page table address register (r/w)
Notes:
First off, DMA can only access the lower meg (some channels can access
16M on ATs) which translates to a 20-bit address. Secondly, DMA cannot
read/write across a physical page boundary (address with lower 16-bits = 0).
This also means that DMA cannot transfer more than 64K (actually 65535
bytes) bytes at a time. To guarantee no boundary conflicts, many
programmers allocate 128KBytes, and find the first page boundary within
that memory space. Here is an example in Borland 'C' to get 65000 bytes:
---- cut ----
unsigned char *data;
unsigned char *aligned;
unsigned long aligned_physical;
...
unsigned long physical;
data=farmalloc(131000L);
if(data==NULL)
{
printf("Memory Allocation Error\n");
exit(1);
}
physical=((unsigned long)FP_OFF(data))+
(((unsigned long)FP_SEG(data))<<4);
aligned_physical=physical+0x0FFFFL;
aligned_physical&=0xF0000L;
aligned=MK_FP((aligned_physical>>4)&0xFFFF,0);
---- cut ----
to have a device read len bytes from the above memory (*aligned) (DMA
channel 1):
---- cut ----
len--;
outportb(0x0A,0x05);
outportb(0x0C,0x00);
outportb(0x0B,0x49);
outportb(0x02,0);
outportb(0x02,0);
outportb(0x83,(aligned_physical>>16)&15);
outportb(0x03,(unsigned char)(len&0xFF));
outportb(0x03,(unsigned char)((len>>8)&0xFF));
outportb(0x0A,0x01);
---- cut ----
to have a device write len bytes from the above memory (*aligned) (DMA
channel 1):
---- cut ----
len--;
outportb(0x0A,0x05);
outportb(0x0C,0x00);
outportb(0x0B,0x45);
outportb(0x02,0);
outportb(0x02,0);
outportb(0x83,(aligned_physical>>16)&15);
outportb(0x03,(unsigned char)(len&0xFF));
outportb(0x03,(unsigned char)((len>>8)&0xFF));
outportb(0x0A,0x01);
---- cut ----